<?php
/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2018/8/29
 * Time: 14:56
 */
namespace app\api\service;

use app\api\model\Order as OrderModel;
use app\api\model\OrderProduct;
use app\api\model\Product;
use app\api\model\UserAddress;
use app\lib\exception\OrderException;
use app\lib\exception\UserException;
use think\Exception;

class OrderService {

//    订单的商品，客户端传递过来的
    protected $oProducts;
//    数据库中查询出来的
    protected $products;
    protected $uid;

    public function place($uid,$oProducts){
//        $oProducts 与 $products 作对比
//        $products从数据库中查出来
        $this->oProducts = $oProducts;
        $this->products = $this->getProductByOrder($oProducts);
        $this->uid = $uid;
        $status = $this->getOrderStatus();
        if(!$status['pass']){
            $status['order_id'] = -1;
//            throw new ProductException(['msg'=>'商品中sz有库存不足','errorCode'=>'20001']);
            return $status;
        }
//       创建订单
//        生成订单快照信息
        $orderSnap = $this->snapOrder($status);
//        print_r($orderSnap);die;
        $order = $this->createOrder($orderSnap);
//        print_r($order);die;
        $order['pass'] = true;
        return $order;
    }

    /**创建生成订单
     * @param $orderSnap
     * @return array
     * @throws Exception
     */
    private function createOrder($orderSnap){
        try{
            $orderNo = date("Ymd").self::buildOrderID();
            $order = new OrderModel();
            $order->user_id = $this->uid;
            $order->order_no = $orderNo;
            $order->total_price = $orderSnap['orderPrice'];
            $order->total_count = $orderSnap['totalCount'];
            $order->snap_img = $orderSnap['snapImg'];
            $order->snap_name = $orderSnap['snapName'];
            $order->snap_address = $orderSnap['snapAddress'];
            $order->snap_items = json_encode($orderSnap['pStatus'],JSON_UNESCAPED_UNICODE);
            $order->save();

            $orderId = $order->id;
            $create_time = $order->create_time;
            foreach ($this->oProducts as &$p) {
                $p['order_id'] = $orderId;
            }
            $oProduct = new OrderProduct();
            $oProduct->saveAll($this->oProducts);
            return [
                'order_no'=>$orderNo,
                'order_id'=>$orderId,
                'create_time'=>$create_time
            ];
        }catch (\Exception $e){
            throw new Exception($e->getMessage());
        }
    }

    /**
     * 订单ID生成器
     * @param $orderTag 订单标识
     * @return string
     */
    public static function buildOrderID($orderTag=null)
    {
        $yCode = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J');
        $orderSn = $yCode[intval(date('Y')) - 2011] . strtoupper(dechex(date('m'))) . date('d') . substr(time(), -5) . substr(microtime(), 2, 5) . sprintf('%02d', rand(0, 99)) . substr(md5(uniqid()),0,14);
        if(!is_null($orderTag)){
            $orderSn .= $orderTag . "-" . $orderSn;
        }
        return $orderSn;
    }

    /**
     * 生成订单快照信息
     * @param $status
     * @return array
     * @throws UserException
     */
    private function snapOrder($status){
        $snap = [
            'orderPrice'=>0,
            'totalCount'=>0,
            'pStatus'=>[],
            'snapAddress'=>'',
            'snapName'=>'',
            'snapImg'=>''
        ];
        $snap['orderPrice'] = $status['orderPrice'];
        $snap['totalCount'] = $status['totalCount'];
        $snap['pStatus'] = $status['pStatusArray'];
        $snap['snapAddress'] = json_encode($this->getUserAddress(),JSON_UNESCAPED_UNICODE);
        $snap['snapName'] = $this->products[0]['name'];
        $snap['snapImg'] = $this->products[0]['main_img_url'];

        if(count($this->products) > 1){
            $snap['snapName'] .= '等';
        }
        return $snap;
    }

    /**
     * 获取用户收货地址
     * @return array|false|\PDOStatement|string|\think\Model
     * @throws Exception
     * @throws UserException
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     */
    private function getUserAddress(){
        $userAddress = UserAddress::where('user_id','=',$this->uid)->find();
        if(!$userAddress){
            throw new UserException(['msg'=>'用户收货地址不存在','errorCode'=>'60001']);
        }
        return $userAddress;
    }


    /**
     * 对外公共方法，根据订单ID，检测库存量
     * @param $orderId
     * @return array
     * @throws OrderException
     * @throws \think\exception\DbException
     */
    public function checkOrderStock($orderId){
        $oProducts = OrderProduct::all(['order_id'=>$orderId]);
        $this->oProducts = $oProducts;
        $this->products = $this->getProductByOrder($oProducts);
        $status = $this->getOrderStatus();
        return $status;
    }


    /**
     * 获取订单状态
     * @return array
     * @throws OrderException
     */
    private function getOrderStatus(){
        $status = [
            'pass'=>true,
            'orderPrice'=>0,
            'totalCount'=>0,
            'pStatusArray'=>[]
        ];

        foreach ($this->oProducts as $oProduct) {
            $pStatus = $this->getProductStatus(
                $oProduct['product_id'],$oProduct['count'],$this->products
            );
//            print_r($pStatus);
            if(!$pStatus['haveStock']){
                $status['pass'] = false;
            }
            $status['orderPrice'] += $pStatus['totalPrice'];
            $status['totalCount'] += $pStatus['count'];
            array_push($status['pStatusArray'],$pStatus);
        }
//        print_r($status);die;
        return $status;
    }

    /**
     * 获取订单商品状态
     * @param $oPID
     * @param $oCount
     * @param $products
     * @return array
     * @throws Exception
     * @throws OrderException
     */
    private  function getProductStatus($oPID,$oCount,$products){
//        print_r([$oPID,$oCount,$products]);
        $pIndex = -1;
        $pStatus = [
            'id'=>null,
            'haveStock'=>false,
            'count'=>0,
            'name'=>'',
            'totalPrice'=>0
        ];

        for ($i=0;$i<count($products);$i++){
//            print_r($oPID);
            if($oPID == $products[$i]['id']){
                $pIndex = $i;
                if($pIndex == -1){
                    throw new OrderException(['msg'=>'id为：'.$oPID.'的商品不存在，创建订单失败']);
                }
                $product = $products[$pIndex];
                $pStatus['id'] = $product['id'];
                $pStatus['name'] = $product['name'];
                $pStatus['count'] = $oCount;
                $pStatus['totalPrice'] = $product['price'] * $oCount;
                if(($product['stock'] - $oCount) >= 0){
                    $pStatus['haveStock'] = true;
                }
                return $pStatus;
            }
        }
    }


    /**
     * 根据订单信息查找真实的商品信息
     * @param $oProducts
     * @return mixed
     * @throws \think\exception\DbException
     */
    private function getProductByOrder($oProducts){
//        根据订单信息查找真实的商品信息
        $oPIDs = [];
        foreach ($oProducts as $oProduct){
            array_push($oPIDs,$oProduct['product_id']);
        }
        return Product::all($oPIDs)->toArray();
    }

}